package pt.inescid.components.policyengine.heimdall.pip;

import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.pdp.base.CesInstance;

public class CachedModel {

	public static final int INITIAL_CUI = 5;
	public static final int ADD_TO_CUI = 1;
	public static final int SUBTRACT_FROM_CUI = 1;

	private String modelDefTag = null;
	private Vector allCesInstances = new Vector();
	private Vector allCuis = new Vector();

	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      Constructor       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public CachedModel(String modelDefTag) {
		this.modelDefTag = modelDefTag;
		this.allCesInstances = new Vector();
		this.allCuis = new Vector();
	}


	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      getEvents       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public Vector getEvents(String cesName, Vector cesParameters,
			NodeInfo currentNode) {
		
		CesInstance currentCesInstance = null;
		int currentCui = Integer.MAX_VALUE;
		for (int i = 0; i < allCesInstances.size(); i++) {
			currentCesInstance = (CesInstance) allCesInstances.elementAt(i);
			
			// check if a similar ces instance is loaded
			if (currentCesInstance.getDefinition().getName().equals(
					cesName)) {
				
				currentCui = ((Integer) allCuis.elementAt(i)).intValue();
				allCuis.setElementAt(new Integer(
						currentCui + ADD_TO_CUI), i);
				
				Vector currentCesParameters = 
					currentCesInstance.getParameters();
				boolean found = true;
				boolean noParameters = false;
				
				if (cesParameters == null && currentCesParameters == null) {
					noParameters = true;
				}
				else if ((cesParameters == null && currentCesParameters != null) ||
					(cesParameters != null && currentCesParameters == null) ||
					cesParameters.size() != currentCesParameters.size()) {
					
					found = false;
				}
				
				if (found && !noParameters) {
					for (int j = 0; j < currentCesParameters.size(); j++) {
						if (!cesParameters.elementAt(j).equals(
								currentCesParameters.elementAt(j))) {
							
							found = false;
							j = currentCesParameters.size();
						}
					}
				}
				
				if (found) {
					
					return (currentCesInstance.getDomain().getLoadedEvents(
							currentNode));
					
				}
			}
		}
		
		return (null);
	} // getEvents


	
	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      updateEventsFromRemoteNode       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public void updateEventsFromRemoteNode(String cesTag, 
			NodeInfo currentNode, Vector newEvents) {
		
		CesInstance currentCesInstance = null;
		boolean foundCes = false;
		for (int i = 0; i < allCesInstances.size(); i++) {
			currentCesInstance = (CesInstance) allCesInstances.elementAt(i);
			
			// check if a similar ces instance is loaded
			if (currentCesInstance.getTag().equals(
					cesTag)) {
				
				foundCes = true;
				i = allCesInstances.size();
			}
		}
		
		if (foundCes) {
			Vector allNodes = currentCesInstance.getDomain().getNodes();
			NodeInfo thisNode = null;
			for (int j = 0; j < allNodes.size(); j++) {
				thisNode = (NodeInfo) allNodes.elementAt(j);
				
				if (thisNode.getHostname().equals(currentNode.getHostname()) &&
						thisNode.getHostport() == currentNode.getHostport()) {
					
					thisNode.setProcEvents(newEvents);
					thisNode.setStatus(NodeInfo.NODE_PROCESSED);
					j = allNodes.size();
				}
			}
		}
	} // updateEventsFromRemoteNode
	
	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      updateEventsFromLocalNode       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public void updateEventsFromLocalNode(CesInstance thisCes, 
			NodeInfo currentNode, Vector newEvents) {
		
		CesInstance currentCesInstance = null;
		boolean foundCes = false;
		for (int i = 0; i < allCesInstances.size(); i++) {
			currentCesInstance = (CesInstance) allCesInstances.elementAt(i);
			
			// check if a similar ces instance is loaded
			if (currentCesInstance.getTag().equals(
					thisCes.getTag())) {
				
				foundCes = true;
				i = allCesInstances.size();
			}
		}
		
		if (!foundCes) {
			try {
				currentCesInstance = (CesInstance) thisCes.clone();
			} catch (CloneNotSupportedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			allCesInstances.add(currentCesInstance);
		}
		
		Vector allNodes = currentCesInstance.getDomain().getNodes();
		NodeInfo thisNode = null;
		for (int j = 0; j < allNodes.size(); j++) {
			thisNode = (NodeInfo) allNodes.elementAt(j);
			
			if (thisNode.getHostname().equals(currentNode.getHostname()) &&
					thisNode.getHostport() == currentNode.getHostport()) {
				
				thisNode.setProcEvents(newEvents);
//				thisNode.setStatus(NodeInfo.NODE_PROCESSED);
				j = allNodes.size();
			}
		}
	} // updateEventsFromLocalNode


	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      getMinimumCui       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public int getMinimumCui() {
		
		int currentCui = Integer.MAX_VALUE;
		int minimumCui = Integer.MAX_VALUE;
		for (int i = 0; i < allCuis.size(); i++) {
			currentCui = ((Integer) allCuis.elementAt(i)).intValue();
			
			if (currentCui < minimumCui) {
				minimumCui = currentCui;
			}
		}
		
		return (minimumCui);		
	} // getMinimumCui

	
	

	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      discardMinimumCui       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public void discardMinimumCui(int minimumCui) {
		
		int currentCui = Integer.MAX_VALUE;
		for (int i = 0; i < allCuis.size(); i++) {
			currentCui = ((Integer) allCuis.elementAt(i)).intValue();
			
			if (currentCui == minimumCui) {
				allCesInstances.removeElementAt(i);
				allCuis.removeElementAt(i);
				
				return;
			}
		}
	} // discardMinimumCui


	
	
	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      decreaseCui       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public void decreaseCui() {
		
		int currentCui = Integer.MAX_VALUE;
		for (int i = 0; i < allCuis.size(); i++) {
			currentCui = ((Integer) allCuis.elementAt(i)).intValue();
			
			allCuis.setElementAt(new Integer(
					currentCui - SUBTRACT_FROM_CUI), i);
		}
	} // decreaseCui
	
	
	
	public String getModelDefTag() {
		return modelDefTag;
	}

}; // CachedNode
